gRPC 통신 및 BFF 아키텍처

gRPC란 무엇인가?

gRPC는 서로 다른 컴퓨터에 있는 프로그램들이 대화할 수 있게 해주는 도구. 한 프로그램이 다른 프로그램의 기능을 호출할 수 있게 해줌.

gRPC 사용 이유

BFF(Backend For Frontend)란?

BFF는 프론트엔드(사용자가 보는 화면)를 위한 전용 백엔드 서버. '데이터 조립공장'

필요한 이유

gRPC + BFF 조합

사용자 앱 → BFF 서버 → 여러 마이크로서비스들 (사용자 정보, 상품 정보, 주문 정보 등)

장점

  1. 속도: 서버 간 통신이 매우 빠름
  2. 안정성: 정해진 규칙대로만 데이터를 주고받음
  3. 유지보수: 각 부분을 독립적으로 관리 가능

간단한 예시

상황: 쇼핑몰 앱에서 사용자 정보를 가져오는 경우

기존 방식 (REST API)

GET /api/user/123
→ 응답: JSON 형태의 사용자 정보

gRPC 방식

GetUser(사용자ID: 123)
→ 응답: 미리 정의된 구조의 사용자 정보

차이점

gRPC 동작 과정

1. Proto 파일 작성 (서버와 클라이언트 공통 계약서)

syntax = "proto3";

// 사용자 서비스 정의 (어떤 기능을 제공할지)
service UserService {
  rpc GetUser(UserRequest) returns (UserResponse);
}

// 요청할 때 보낼 데이터
message UserRequest {
  string user_id = 1;  // 1번: 사용자 ID
}

// 응답할 때 받을 데이터  
message UserResponse {
  string user_id = 1;  // 1번: 사용자 ID
  string name = 2;     // 2번: 이름
  string email = 3;    // 3번: 이메일
  bool success = 4;    // 4번: 성공 여부
}

2. 전체 통신 흐름

클라이언트                          서버
    |                               |
    | 1. gRPC 요청 (바이너리)          |
    |   사용자ID: "123"               |
    |------------------------------>|
    |                               | 2. 바이너리 → UserRequest 객체
    |                               | 3. 비즈니스 로직 처리
    |                               |    - 데이터베이스 조회
    |                               |    - 실제 사용자 데이터 찾기
    |                               | 4. UserResponse 객체 생성
    |                               |    - proto 규칙에 맞게 데이터 포장
    |                               | 5. UserResponse → 바이너리
    | 6. gRPC 응답 (바이너리)          |
    |   이름: "홍길동"                |
    |   이메일: "hong@example.com"    |
    |<------------------------------|
7. 바이너리 → UserResponse 객체       |

3. 핵심 포인트

송수신 과정

1. 송신측 (클라이언트)

UserRequest.newBuilder()
  .setUserId("123")    // user_id 필드 → 필드번호 1로 변환
  .setName("홍길동")   // name 필드 → 필드번호 2로 변환  
  .setAge(25)         // age 필드 → 필드번호 3으로 변환
  .build();

↓ 자동 변환

바이너리 예시 : 0x0A 0x03 0x31 0x32 0x33 0x12 0x09 0xED 0x99 0x8D 0xEA 0xB8 0xB8 0xEB 0x8F 0x99 0x1A 0x11 

2. 수신측 (서버)

바이너리 예시 : 0x68 0x6F 0x6E 0x67 0x40 0x65 0x78 0x61 0x6D 0x70 0x6C 0x65 0x2E 0x63 0x6F 0x6D 0x20 0x01

↓ 자동 해석

필드1 = "123" → getUserId() 메서드로 접근 가능
필드2 = "홍길동" → getName() 메서드로 접근 가능
필드3 = 25 → getAge() 메서드로 접근 가능


크기 비교

JSON 방식

json

{"user_id": "123", "name": "홍길동", "age": 25}

52바이트 (필드명까지 다 포함)

gRPC 바이너리

[1]["123"][2]["홍길동"][3][25]

약 15바이트 (필드명 없이 번호만)

심화: gRPC 통신 및 BFF 아키텍처

gRPC 개요 gRPC는 Google에서 개발한 고성능 오픈소스 RPC(Remote Procedure Call) 프레임워크.

BFF(Backend For Frontend) 패턴 BFF는 특정 프론트엔드 애플리케이션 유형에 최적화된 백엔드 서비스를 구축하는 아키텍처 패턴.

통신 흐름

프론트엔드 클라이언트 (HTTP/JSON) → BFF 계층 (HTTP → gRPC 변환) → 마이크로서비스 (gRPC 처리)

주요 장점


최근 동향: JSON-RPC의 부상과 성능 비교

JSON-RPC란? JSON-RPC는 JSON을 사용하는 원격 프로시저 호출 프로토콜. gRPC와 비슷한 목적이지만 더 간단한 접근 방식 제공.

주목받는 이유

Google의 A2A (Agent-to-Agent) 채택

MCP (Model Context Protocol)

성능 비교: JSON-RPC vs gRPC

속도 측면에서는 gRPC가 압도적으로 빠름!

데이터 크기 비교

JSON-RPC (텍스트 형태)

{
  "jsonrpc": "2.0",
  "result": {
    "userId": "user_12345",
    "name": "홍길동",
    "email": "hong@example.com",
    "status": "ACTIVE"
  },
  "id": 1
}

약 150-200 바이트

gRPC (바이너리 형태)

바이너리 데이터로 압축된 형태 예시 :  0x0A 0x03 0x31 0x32 0x33 0x12 0x09 0xED 0x99 0x8D 0xEA 0xB8 0xB8 0xEB 0x8F 0x99 0x1A 0x11 0x68 0x6F 0x6E 0x67 0x40 0x65 0x78 0x61 0x6D 0x70 0x6C 0x65 0x2E 0x63 0x6F 0x6D 0x20 0x01

약 50-80 바이트

처리 속도 비교

구분 JSON-RPC gRPC 차이
직렬화 속도 느림 (텍스트 파싱) 빠름 (바이너리) gRPC 3-5배 빠름
네트워크 전송 느림 (큰 데이터) 빠름 (작은 데이터) gRPC 2-3배 빠름
역직렬화 속도 느림 (JSON 파싱) 빠름 (바이너리) gRPC 3-5배 빠름

JSON-RPC가 주목받는 이유

성능이 전부가 아니기 때문!

JSON-RPC vs gRPC 비교

특징 JSON-RPC gRPC
성능 보통 매우 높음
개발 복잡성 매우 간단 상대적으로 복잡
디버깅 쉬움 (JSON은 읽기 쉬움) 어려움 (바이너리 형태)
AI 통합 매우 좋음 보통
설정 최소한의 설정 복잡한 설정 필요

실제 사용 시나리오별 선택

고성능이 중요한 경우 → gRPC

마이크로서비스 간 초당 10,000건 처리
→ gRPC의 성능 우위가 명확히 드러남

개발 편의성이 중요한 경우 → JSON-RPC

AI 에이전트가 웹 API 호출
→ JSON-RPC가 훨씬 간단하고 실용적

언제 무엇을 사용할까?

gRPC를 사용하면 좋은 경우

JSON-RPC를 사용하면 좋은 경우

BFF를 사용하면 좋은 경우

결론

성능만 보면 gRPC가 압도적으로 빠르지만, 현실에서는 상황에 따라 선택해야 함:

Google이 A2A에서 JSON-RPC를 선택한 이유도 성능보다는 AI 에이전트들이 쉽게 이해하고 사용할 수 있는 단순함과 호환성 때문.

심화

성능 순서

일반적인 속도 순서:

gRPC > JSON-RPC ≈ REST API

JSON-RPC와 REST API는 거의 비슷한 성능

왜 비슷한 성능일까?

공통점들:

JSON-RPC:

{
  "jsonrpc": "2.0",
  "method": "getUser", 
  "params": {"userId": "123"},
  "id": 1
}

REST API:

POST /api/users/123
{
  "action": "get"
}

세부 차이점

JSON-RPC의 장점:

REST API의 단점:

실제 성능 비교

데이터 크기 (같은 응답 기준):

JSON-RPC:

{
  "jsonrpc": "2.0",
  "result": {"name": "홍길동", "email": "hong@example.com"},
  "id": 1
}

약 80-90바이트

REST API:

{
  "status": "success",
  "data": {"name": "홍길동", "email": "hong@example.com"}
}

약 75-85바이트

gRPC:

[바이너리 형태]

약 25-35바이트

처리 속도 비교

구분 REST API JSON-RPC gRPC
직렬화 JSON 파싱 JSON 파싱 바이너리
네트워크 HTTP/1.1 HTTP/1.1 HTTP/2
오버헤드 URL + 메서드 메서드명만 필드번호
상대속도 1x 1.1x 3-5x

실제 상황에서는?

JSON-RPC가 REST보다 약간 빠른 경우:

하지만 차이는 미미함:

결론

성능 순서:

  1. gRPC: 압도적으로 빠름 (3-5배)
  2. JSON-RPC: REST보다 약간 빠름 (10-20% 정도)
  3. REST API: 기준점

JSON-RPC를 선택하는 이유는 성능보다는: